package com.example.stuwork.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.example.stuwork.service.OSSService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.UUID;

/**
 * OSS服务实现类
 */
@Service
public class OSSServiceImpl implements OSSService {
    
    private static final Logger logger = LoggerFactory.getLogger(OSSServiceImpl.class);

    // 硬编码OSS配置，避免配置文件冲突
    private final String endpoint = "oss-cn-shenzhen.aliyuncs.com";
    private final String accessKeyId = "LTAI5tKSjpi7WeGnMnuSLUed";
    private final String accessKeySecret = "IFen3WRdwkhaNNdtWNWTdd7Yri4hAH";
    private final String bucketName = "stu-work";
    private final String urlPrefix = "https://stu-work.oss-cn-shenzhen.aliyuncs.com";

    /**
     * 上传文件到OSS
     *
     * @param file 文件对象
     * @return 文件访问URL
     */
    @Override
    public String uploadFile(MultipartFile file) {
        logger.info("OSS上传开始 - 使用硬编码配置 - endpoint=[{}], bucketName=[{}], urlPrefix=[{}]", 
                endpoint, bucketName, urlPrefix);
        
        if (file == null || file.isEmpty()) {
            logger.error("上传文件为空");
            return null;
        }
        
        // 获取文件名
        String originalFilename = file.getOriginalFilename();
        logger.info("准备上传文件: {}", originalFilename);
        
        // 使用UUID生成文件名，防止文件名重复
        String fileName = generateFileName(originalFilename);
        logger.info("生成的唯一文件名: {}", fileName);

        OSS ossClient = null;
        try {
            // 创建OSSClient实例
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            logger.info("OSS客户端创建成功");
            
            // 获取文件输入流
            InputStream inputStream = file.getInputStream();
            
            // 创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            // 设置Content-Type
            String contentType = getContentType(fileName);
            objectMetadata.setContentType(contentType);
            // 设置Content-Length
            objectMetadata.setContentLength(file.getSize());
            logger.info("设置文件元数据: contentType=[{}], size=[{}]", contentType, file.getSize());
            
            // 上传文件
            logger.info("开始上传文件到OSS，bucketName=[{}], fileName=[{}]", bucketName, fileName);
            ossClient.putObject(bucketName, fileName, inputStream, objectMetadata);
            logger.info("文件上传成功");
            
            // 构建文件访问URL - 使用简单的URL格式
            String fileUrl = urlPrefix + "/" + fileName;
            
            // 添加原始文件名作为查询参数
            if (originalFilename != null && !originalFilename.isEmpty()) {
                try {
                    // 使用BASE64编码原始文件名
                    String encodedName = java.util.Base64.getEncoder().encodeToString(originalFilename.getBytes("UTF-8"));
                    fileUrl += "?name=" + encodedName;
                    logger.info("添加原始文件名到URL: {}，编码后: {}", originalFilename, encodedName);
                } catch (Exception e) {
                    logger.warn("编码原始文件名失败: {}", e.getMessage());
                }
            }
            
            logger.info("构建文件URL: {}", fileUrl);
            
            // 验证URL格式
            if (!fileUrl.startsWith("http")) {
                logger.error("生成的文件URL无效，不包含http前缀: {}", fileUrl);
                logger.error("正在尝试修复URL前缀...");
                
                // 尝试修复URL
                if (urlPrefix != null && !urlPrefix.isEmpty()) {
                    if (!urlPrefix.startsWith("http")) {
                        fileUrl = "https://" + urlPrefix.replaceAll("^[/\\\\]+", "") + "/" + fileName;
                    } else {
                        // URL前缀已经包含http，可能是其他格式问题
                        fileUrl = urlPrefix.replaceAll("/+$", "") + "/" + fileName;
                    }
                    logger.info("修复后的URL: {}", fileUrl);
                } else {
                    logger.error("URL前缀为空，无法构建有效URL");
                    return null;
                }
            }
            
            // 再次验证
            if (!fileUrl.startsWith("http") || !fileUrl.contains("/")) {
                logger.error("即使修复后，URL仍然无效: {}", fileUrl);
                return null;
            }
            
            logger.info("返回最终文件URL: {}", fileUrl);
            return fileUrl;
        } catch (Exception e) {
            logger.error("文件上传失败: ", e);
            return null;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
                logger.info("OSS客户端已关闭");
            }
        }
    }

    /**
     * 从OSS删除文件
     *
     * @param url 文件URL
     * @return 是否删除成功
     */
    @Override
    public boolean deleteFile(String url) {
        logger.info("准备删除文件: {}", url);
        
        if (url == null || url.trim().isEmpty()) {
            logger.error("删除失败：URL为空");
            return false;
        }
        
        // 检查URL格式
        if (!url.startsWith("http")) {
            logger.error("删除失败：URL格式无效，不是以http开头: {}", url);
            return false;
        }
        
        logger.info("OSS删除 - 使用硬编码配置 - endpoint=[{}], bucketName=[{}], urlPrefix=[{}]", 
                endpoint, bucketName, urlPrefix);
        
        OSS ossClient = null;
        try {
            // 获取OSS中的对象名
            String objectName = extractObjectNameFromUrl(url);
            if (objectName == null || objectName.trim().isEmpty()) {
                logger.error("无法从URL提取对象名: {}", url);
                return false;
            }
            
            logger.info("从URL [{}] 提取对象名: [{}]", url, objectName);
            
            // 创建OSSClient实例
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            logger.info("OSS客户端创建成功");
            
            // 检查对象是否存在
            boolean exists = ossClient.doesObjectExist(bucketName, objectName);
            if (!exists) {
                logger.error("OSS对象不存在：bucketName=[{}], objectName=[{}]", bucketName, objectName);
                return false;
            }
            
            // 删除文件
            logger.info("开始删除OSS文件，bucketName=[{}], objectName=[{}]", bucketName, objectName);
            ossClient.deleteObject(bucketName, objectName);
            logger.info("OSS删除命令执行成功");
            
            // 再次检查对象是否存在
            boolean stillExists = ossClient.doesObjectExist(bucketName, objectName);
            if (stillExists) {
                logger.error("OSS对象删除失败，文件仍然存在: bucketName=[{}], objectName=[{}]", bucketName, objectName);
                return false;
            }
            
            logger.info("OSS对象删除成功确认: bucketName=[{}], objectName=[{}]", bucketName, objectName);
            return true;
        } catch (Exception e) {
            logger.error("OSS删除时发生异常: {}", e.getMessage(), e);
            return false;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
                logger.info("OSS客户端已关闭");
            }
        }
    }

    /**
     * 从URL中提取OSS对象名
     *
     * @param url 完整的OSS URL
     * @return OSS对象名
     */
    private String extractObjectNameFromUrl(String url) {
        try {
            // 移除查询参数
            if (url.contains("?")) {
                url = url.substring(0, url.indexOf("?"));
            }
            
            // 处理URL前缀
            String effectiveUrlPrefix = urlPrefix;
            if (!effectiveUrlPrefix.endsWith("/")) {
                effectiveUrlPrefix = effectiveUrlPrefix + "/";
            }
            
            // 确保URL以我们的URL前缀开始
            if (!url.startsWith(effectiveUrlPrefix)) {
                logger.warn("URL不以配置的前缀开始: url=[{}], prefix=[{}]", url, effectiveUrlPrefix);
                
                // 尝试从URL中提取对象名
                java.net.URL parsedUrl = new java.net.URL(url);
                String path = parsedUrl.getPath();
                if (path.startsWith("/")) {
                    path = path.substring(1);
                }
                logger.info("从URL路径提取的对象名: [{}]", path);
                return path;
            }
            
            // 正常情况：从URL前缀之后提取对象名
            String objectName = url.substring(effectiveUrlPrefix.length());
            logger.info("从URL [{}] 提取对象名: [{}]", url, objectName);
            return objectName;
        } catch (Exception e) {
            logger.error("提取对象名时出错: {}", e.getMessage(), e);
            
            // 回退方案：直接从URL中提取最后一个路径部分
            try {
                String[] parts = url.split("/");
                String fileName = parts[parts.length - 1];
                if (fileName.contains("?")) {
                    fileName = fileName.substring(0, fileName.indexOf("?"));
                }
                logger.info("使用回退方案提取的对象名: [{}]", fileName);
                return fileName;
            } catch (Exception ex) {
                logger.error("回退提取对象名也失败: {}", ex.getMessage());
                return null;
            }
        }
    }

    /**
     * 生成文件名
     *
     * @param originalFilename 原始文件名
     * @return 新文件名
     */
    @Override
    public String generateFileName(String originalFilename) {
        logger.info("生成文件名，原始文件名: {}", originalFilename);
        
        if (originalFilename == null || originalFilename.trim().isEmpty()) {
            logger.warn("原始文件名为空，使用时间戳");
            return System.currentTimeMillis() + ".unknown";
        }

        try {
            // 获取文件扩展名
            String extension = "";
            if (originalFilename.contains(".")) {
                extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            }
            
            // 使用UUID确保唯一性
            String uuid = UUID.randomUUID().toString().replace("-", "");
            
            // 使用BASE64编码原始文件名并作为参数添加到URL中
            String encodedName = java.util.Base64.getEncoder().encodeToString(originalFilename.getBytes("UTF-8"));
            
            logger.info("文件扩展名: {}, 生成的UUID: {}, BASE64编码后的文件名: {}", extension, uuid, encodedName);
            
            // 最终文件名: UUID + 扩展名
            return uuid + extension;
        } catch (Exception e) {
            logger.error("生成文件名失败: ", e);
            return UUID.randomUUID().toString() + ".unknown";
        }
    }

    /**
     * 获取文件的contentType
     * @param fileName 文件名
     * @return contentType
     */
    private String getContentType(String fileName) {
        // 文件的后缀名
        String extension = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
        
        // 根据后缀名设置contentType
        if (extension.equals(".jpg") || extension.equals(".jpeg")) {
            return "image/jpeg";
        } else if (extension.equals(".png")) {
            return "image/png";
        } else if (extension.equals(".gif")) {
            return "image/gif";
        } else if (extension.equals(".pdf")) {
            return "application/pdf";
        } else if (extension.equals(".doc") || extension.equals(".docx")) {
            return "application/msword";
        } else if (extension.equals(".xls") || extension.equals(".xlsx")) {
            return "application/vnd.ms-excel";
        } else if (extension.equals(".ppt") || extension.equals(".pptx")) {
            return "application/vnd.ms-powerpoint";
        } else if (extension.equals(".txt")) {
            return "text/plain";
        } else if (extension.equals(".mp4")) {
            return "video/mp4";
        } else if (extension.equals(".zip")) {
            return "application/zip";
        } else if (extension.equals(".rar")) {
            return "application/x-rar-compressed";
        }
        // 默认返回二进制流
        return "application/octet-stream";
    }
} 